<template>
  <div class="containers">
    <div class="canvas" ref="canvas"></div>
    <panelCom class="panelBpmn" ref="panel" @saveUserTask="saveUserTask" @channel="channel" :element="element" :fields="fields" v-if="taskDrawer"/>
    <connection class="panelBpmn" ref="connection" @saveTask="saveTask" @channel="channel" :element="element" :fields="fields" v-if="connectionDrawer"/>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import panelCom from './components/panel.vue'
import connection from './components/connection.vue'
import { commonAction, handleData } from '@/utils/common';
import { busConfigStore } from '../store/busConfigStore';
// 引入相关的依赖
import { getXmlStr } from './bpmn/features/palette/initXmlStr' // 这里是直接引用了xml字符串
import CustomModeler from './bpmn/features/palette/customModeler'
import customTranslate from './bpmn/features/palette/chinesization/customTranslate'
@Component({
  components: { panelCom, connection }
})

export default class extends Vue {
  [x: string]: any;
  private unwatch: any = null;
  private isSaveXml = false
  private connectionDrawer = false
  private modelName = ''
  private fields = []
  private $route: any;
  private taskDrawer = false
  private element: any = {}
  private xmlStr = ''
  private loading = false
  // bpmn建模器
  private bpmnModeler: any = null
  private container: any = null
  private canvas: any = null

  private get account () {
    return (this.$store as any).state.common.session.account._id
  }

  private init () {
    // this.loading = true
    const canvas = this.$refs.canvas
    const palette = this.$refs.palette
    const customTranslateModule = {
      translate: ['value', customTranslate]
    }
    if (this.bpmnModeler) {
      this.bpmnModeler.destroy();
    }
    (this.$refs as any).canvas.innerHTML = ''
    // 建模
    this.bpmnModeler = new CustomModeler({
      container: canvas,
      additionalModules: [
        // 汉化
        customTranslateModule
      ]
    })
    this.transformCanvas()
    this.addBpmnListener()
    this.handleModeler()
  }

  private handleModeler () {
    // 监听节点选择变化
    this.bpmnModeler.on('selection.changed', e => {
      console.log('监听节点选择变化')
      if (!e.newSelection[0]) {
        return false
      } else {
        this.element = e.newSelection[0]
      }
      console.log(this.element)
      // 审批类型
      if (this.element.type === 'bpmn:UserTask') {
        this.connectionDrawer = false
        this.taskDrawer = true
        this.$nextTick(() => {
          (this.$refs.panel as any).getConfigById(this.element.id)
        })
      } else if (this.element.type === 'bpmn:SequenceFlow' && this.element?.source.type === 'bpmn:ExclusiveGateway') {
        this.taskDrawer = false
        this.connectionDrawer = true
        this.$nextTick(() => {
          (this.$refs.connection as any).getConfigById(this.element)
        })
      }
    })
    //  监听节点属性变化
    // this.bpmnModeler.on('element.changed', e => {
    //   console.log('监听节点属性变化')
    //   const { element } = e
    //   if (!element) {
    //     return false
    //   }
    // })
  }

  private saveUserTask (data: any) {
    this.taskDrawer = false
    const { assignInfo, assignType } = data.dealConfig
    if (assignType === 1) {
      const data1 = {}
      data1['camunda:assignee'] = assignInfo
      this.updateProperties(data1)
    } else {
      const data1 = {}
      data1['camunda:assignee'] = null
      this.updateProperties(data1)
    }
    this.isSaveXml = true
  }

  private saveTask (data: any) {
    this.taskDrawer = false
    this.connectionDrawer = false
    // this.updateProperties(data)
    const modeling = this.bpmnModeler.get('modeling')
    const moddle = this.bpmnModeler._moddle;
    const conditionExpression = moddle.create('bpmn:FormalExpression', {
      // eslint-disable-next-line no-template-curly-in-string
      body: '${gatewayConditionService.checkCondition(execution,' + '"' + this.element.id + '")}'
    });
    modeling.updateProperties(this.element, {
      conditionExpression,
      name: data.name
    });
  }

  private updateProperties (properties) {
    const modeling = this.bpmnModeler.get('modeling')
    modeling.updateProperties(this.element, properties)
  }

  // 监听流程图改变事件
  private addBpmnListener () {
    const that = this
    this.bpmnModeler.on('commandStack.changed', () => {
      that.saveDiagram((err, xml) => {
        that.setEncoded(err ? null : xml)
      })
    })
  }

  private saveDiagram (done) {
    // 把传入的done再传给bpmn原型的saveXML函数调用
    this.bpmnModeler.saveXML({ format: true }, (err, xml) => {
      done(err, xml)
    })
  }

  private addListWatch () {
    busConfigStore.workflowChange = false;
    if (this.unwatch) {
      this.unwatch();
    }
    this.unwatch = this.$watch(
      'xmlStr',
      () => {
        busConfigStore.workflowChange = true;
        this.unwatch();
      },
      { deep: true }
    );
  }

  private setEncoded (data) {
    // 获取到图的xml，保存就是把这个xml提交给后台
    this.xmlStr = data
    if (this.isSaveXml) {
      this.saveXml()
    }
    console.log(this.xmlStr)
  }

  private saveXml (isdeploy?: boolean) {
    commonAction({ url: '/server-flow/action/definition/process/save', method: 'post', data: { bpmn: this.xmlStr } }).then(res => {
      if (res.success) {
        busConfigStore.workflowChange = false;
        this.isSaveXml = false
        if (isdeploy) {
          commonAction({ url: '/server-flow/action/definition/deploy', method: 'post', data: { workModelId: this.$route.params.businessId } }).then(res1 => {
            if (res1.success) {
              this.$message.success('发布成功')
            }
          })
        }
      }
    })
  }

  // 将字符串转成图显示出来
  private transformCanvas () {
    this.bpmnModeler.importXML(this.xmlStr, (err) => {
      if (!err) {
        this.adjustPalette()
      }
      // 让图能自适应屏幕
      const canvas = this.bpmnModeler.get('canvas')
      canvas.zoom('fit-viewport', 'auto')
    })
  }

  private adjustPalette () {
    console.log('111')
  }

  private save () {
    this.saveXml(true)
  }

  private channel () {
    this.taskDrawer = false
    this.connectionDrawer = false
  }

  private getConfig () {
    commonAction({ url: '/server-work/action/workOrderModel/getConfig', method: 'post', data: { modelId: this.$route.params.businessId, queryFieldType: 1 } }).then(res => {
      if (res.success) {
        this.modelName = res.data.modelName
        this.fields = res.data.fields || []
      }
    })
  }

  private getProcess () {
    commonAction({ url: `/server-flow/action/definition/process?workModelId=${this.$route.params.businessId}`, method: 'get' }).then(res => {
      if (res.success) {
        this.xmlStr = res.data.bpmn || getXmlStr(`process_${this.account}_${this.$route.params.businessId}`)
        this.init()
        this.addListWatch()
      }
    })
  }

  private mounted () {
    if (!busConfigStore.serviceList.length) {
      commonAction({
        url: '/server-work/action/serviceGroup/listAll',
        method: 'post'
      }).then(res => {
        if (res.success) {
          handleData(res.data.serviceGroupList, 'service')
        }
      })
    }
    this.getProcess()
    this.getConfig()
  }
}
</script>
<style scoped lang="stylus">
.panelBpmn {
  position: fixed;
  right: 0;
  top: 0;
  z-index 1000;
  width: 520px;
  box-shadow: rgb(0 0 0 / 30%) 0px 0px 8px;
  height: calc(100% - 56px);
  overflow-y: auto;
}
.containers{
	position: absolute;
	width: 100%;
	height: 100%;
  background: #f3f5f7;
  background-size: 20px 20px;
  background-image: -webkit-radial-gradient(#e0e6f0 2px, rgba(0,0,0,0) 2px);
  background-image: radial-gradient(#e0e6f0 2px, rgba(0,0,0,0) 2px);
}
.canvas{
	width: 100%;
	height: 100%;
}
.panel{
	position: fixed;
	right: 0;
	top: 0;
	width: 520px;
  box-shadow: rgb(0 0 0 / 30%) 0px 0px 8px;
  height: 100%;
  overflow-y: auto;
  background-color: #fff
}
/deep/.title {
  font-weight: 400;
  color: #303753;
  margin-bottom: 12px
}
</style>
